Technical Note TN2018
Importing animated GIFs

目次

このテクニカルノートでは、GIF ファイルまたは dataref に 2 つ以上のフレームが含まれているかどうかを確認する方法、および GIF ファイルがアニメーション化されている場合でも、GraphicsImportGetImageCount1 の値を戻す理由を説明します。また、QuickTime 5 の新しい 2 つの API、 CanQuickTimeOpenFileCanQuickTimeOpenDataRef を紹介します。これらの API は、ファイルまたは dataref をムービーとして開けるのかどうか、あるいは Graphics Importer を使って開けるかどうかを QuickTime に問い合わせるために使います。

 更新:[2001 年 4 月 17 日]






概要

GIF Graphics Importer は、アニメーション GIF の最初のフレームしか表示しないため、GIF Graphics Importer の GraphicsImportGetImageCount 関数を呼び出すと、1 の値が戻されます。

通常、Graphics Importer は時間を認識せず、キーフレームと差分フレームを組み合わせる方法も知りません。さらに、アニメーションの差分フレームを表示しても、そこに至るまでのフレームを先にすべて描画しなければ、大体の場合は、あまりきれいに表示されません。

これに対して、Movie Toolbox は時間を認識し、差分フレームを含むアニメーションを処理する方法を知っています。そのため、アニメーション GIF の残りのフレームを描画するには、GIF をムービーとしてインポートします。

GIF ファイルに 2 つ以上のフレームが含まれているかどうかを調べるには、最初に GIF をムービーとして開き、次にビデオトラックのフレームの数をカウントします。複数のフレームまたはサンプルがある場合は、ムービーとして扱います。フレームまたはサンプルが 1 つしかなければ、GIF ファイルは単一の静止画像なので、GIF Graphics Importer を代わりに使用できます。

GetAnimatedGIFMovieFromFileリスト 1 参照)は、NewMovieFromFile を使ってファイルを開いた後、フレームの数をカウントします。開いた GIF ファイルがアニメーション GIF なら、有効な非アクティブのムービーが戻されます。GIF ファイルが単一の画像の場合は NULL が返されます。この場合、呼び出し側は Graphics Importer を使用できます。

NewMovieFromFilenewMovieActive フラグを渡さなければ、GIF ファイルをより高速にムービーとして開けます。最終的にムービーを使うことにした場合は(アニメーション GIF ファイルだったため)、SetMovieActive を呼び出して、ムービーをアクティブにします。

リスト 2 では、GetAnimatedGIFMovieFromFile のもう 1 つの実装例を示します。エイリアスデータ参照を作成した後、GetAnimatedGIFMovieFromDataRef (リスト 3 参照)を呼び出します。データ参照を扱えるようにすることにより、メモリや URL からアニメーション GIF ファイルを開けるようになります。

リスト 3 では、GetAnimatedGIFMovieFromDataRef が、リスト 1 と同じ作業を、データ参照を使用して実行する方法を示します。

リスト 4 では、CreateGIFHandleDataReference が、ファイルタイプ拡張子として 'GIFf' を追加したハンドルデータ参照を作成する方法を示します。メモリに GIF 画像がある場合は、GetAnimatedGIFMovieFromDataRef を呼び出す前に、この関数を使って、ハンドルデータ参照を簡単に作成できます。データ参照ハンドルは、使い終わったら忘れずに破棄してください。


注:
実際には、リスト 4 のデータ参照の作成を除いて、上記のコードで GIF に固有の処理はありません。ここでの説明のためだけに、GetAnimatedGIFMovie という名前にしているにすぎません。


先頭に戻る

QuickTime 5 の新機能

QuickTime 5 には、新しい 2 つの API が追加されています。これらの API を使って、ファイルまたはデータ参照をムービーとして開けるか、または Graphics Importer を使って開けるか、あるいはその両方なのかを判別できます。 CanQuickTimeOpenFile は、ファイルまたは指定されたファイルタイプが Graphics Importer を使って開けるのか、またはムービーとして開けるのかどうかを判別します。

OSErr CanQuickTimeOpenFile(FSSpecPtr     fileSpec,
                           OSType        fileType,
                           OSType        fileNameExtension,
                           Boolean *     outCanOpenWithGraphicsImporter,
                           Boolean *     outCanOpenAsMovie,
                           Boolean *     outPreferGraphicsImporter,
                           UInt32        inFlags);

CanQuickTimeOpenDataRef は、ファイルではなくデータ参照を使うことを除けば、CanQuickTimeOpenFile と同じです。

OSErr CanQuickTimeOpenDataRef(Handle      dataRef,
                              OSType      dataRefType,
                              Boolean *   outCanOpenWithGraphicsImporter,
                              Boolean *   outCanOpenAsMovie,
                              Boolean *   outPreferGraphicsImporter,
                              UInt32      inFlags);

特に必要ではないパラメータには NULL を渡します。

inFlags パラメータには、次のような Graphics Importer の検索動作を変更するフラグを指定します。

  • kQTDontUseDataToFindImporter ――ファイルのデータを使いません。検索速度は上がりますが、QuickTime が、既知のファイルタイプまたはファイル名サフィックスによって識別されていないファイルは開けないと報告します。

  • kQTDontLookForMovieImporterIfGraphicsImporterFound ――ファイル開く方法が 1 つ検出されたらすぐに検索を停止します。ファイルを Graphics Importer を使って開けるのか、あるいはムービーとして開けるのか確認したいが、どちらで開いても構わない場合に、このフラグを使います。

  • kQTAllowOpeningStillImagesAsMovies ――静止画像をムービーとして開くことを検討します。セットしてあると、Graphics Importer を使って開けるファイルを、ムービーとしても開けると自動的に報告します。

  • kQTAllowImportersThatWouldCreateNewFile ――新しいファイルを作成するインポータを含みます。クリアの場合は、新しいファイルを作成せずに、その場にインポートできるインポータのみを含みます。

  • kQTAllowAggressiveImporters ――従来、ムービーとして考えられない PICT や TEXT などのファイルタイプ用のムービーインポータを含める場合にセットします。

新しい CanQuickTimeOpenFile/DataRef の呼び出しの詳細については、QuickTime 5 Developer Delta Documentation を参照してください。

// GIF ファイルがアニメーション化されている場合は、
// ムービーを戻し、それ以外の場合は NULL を戻す。
Movie GetAnimatedGIFMovieFromAFile(const FSSpec *inFile)
{
    Movie    theMovie = NULL;
    short    theRefNum = 0;
    long    theNumberOfSamples = 0;
    OSErr     err = noErr;

    err = OpenMovieFile(inFile, &theRefNum, fsRdPerm);
    if (err) goto done;

    err = NewMovieFromFile(&theMovie, theRefNum, NULL, NULL, 0, NULL);
    CloseMovieFile(theRefNum);
    if (err || NULL == theMovie) goto done;

    theNumberOfSamples =
            GetMediaSampleCount(GetTrackMedia(GetMovieIndTrack(theMovie, 1)));

    if (theNumberOfSamples == 1 ) {
        DisposeMovie(theMovie);
        theMovie = NULL;
    }

done:
    return theMovie;
}

リスト 1 GetAnimatedGIFMovieFromFile


// GIF ファイルがアニメーション化されている場合は、
// ムービーを戻し、それ以外の場合は NULL を戻す。
Movie GetAnimatedGIFMovieFromFile(const FSSpec *inFile)
{
    Movie         theMovie = NULL;
    AliasHandle theAlias = NULL;
    OSErr         err = noErr;

    err = QTNewAlias(inFile, &theAlias, true);
    if (err) goto done;

    theMovie = GetAnimatedGIFMovieFromDataRef((Handle)theAlias, rAliasType);
    DisposeHandle((Handle)theAlias);

done:
    return theMovie;
}

リスト 2 GetAnimatedGIFMovieFromFile (エイリアスデータ参照を使用)


// GIF ファイルがアニメーション化されている場合は、
// ムービーを戻し、それ以外の場合は NULL を戻す。
Movie GetAnimatedGIFMovieFromDataRef(Handle inDataRef, OSType inDataRefType)
{
    Movie    theMovie = NULL;
    long    theNumberOfSamples = 0;
    OSErr    err = noErr;

    if (NULL == inDataRef) goto done;

    err = NewMovieFromDataRef(&theMovie, 0, NULL, inDataRef, inDataRefType);
    if (err || NULL == theMovie ) goto done;

    theNumberOfSamples =
            GetMediaSampleCount(GetTrackMedia(GetMovieIndTrack(theMovie, 1)));

    if (theNumberOfSamples == 1 ) {
        DisposeMovie(theMovie);
        theMovie = NULL;
    }

done:
    return theMovie;
}

リスト 3 GetAnimatedGIFMovieFromDataRef


// 'GIFf' ファイルタイプ拡張を使って、dataRef ハンドルを作成する。
Handle CreateGIFHandleDataReference(Handle inData)
{
    Handle    theDataRef = NULL;
    long    theFileTypeAtom[3] = {0};
    OSErr     err = noErr;

    // データのデータ参照ハンドルを作成する
    err = PtrToHand(&inData, &theDataRef, sizeof(Handle));
    if (err) goto done;

    // ファイル名がない
    err = PtrAndHand("¥p", theDataRef, 1);
    if (err) goto done;

    // 'GIFf' 'ftyp' アトム dataRef 拡張子を付与する
    theFileTypeAtom[0] = EndianU32_NtoB(sizeof(long) * 3);
    theFileTypeAtom[1] = EndianU32_NtoB(kDataRefExtensionMacOSFileType);
    theFileTypeAtom[2] = EndianU32_NtoB(kQTFileTypeGIF);

    err = PtrAndHand(theFileTypeAtom, theDataRef, sizeof(long) * 3);

done:
    if (theDataRef && err) {
        DisposeHandle(theDataRef);
        theDataRef = NULL;
    }

    return theDataRef;
}

リスト 4 CreateGIFHandleDataReference


先頭に戻る

ダウンロード

Acrobat gif

このテクニカルノートの PDF 版

ダウンロード


先頭に戻る